package com.gitee.apanlh.util.base;

import com.gitee.apanlh.util.valid.ValidParam;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 	String操作类
 * 
 * 	@author Pan
 */
public class StringUtils {
	
	/** 格式化字符串格式 */
	private static final String FORMAT_DELIM_STR = "{}";
	/** 下划线转换驼峰 */
	private static final String LINE_TAG = "_";
	/** true标识 */
	public static final String TRUE_STR = "true";
	/** false标识 */
	public static final String FALSE_STR = "false";
	
	/**
	 * 	构造函数
	 *
	 * 	@author Pan
	 */
	private StringUtils() {
		//	不允许外部实例
		super();
	}
	
	/**	
	 * 	结尾追加字符串
	 * 	
	 * 	@author Pan
	 * 	@param 	str1	字符串1
	 * 	@param 	str2	字符串2
	 * 	@return	String
	 */
	public static String append(String str1, String str2) {
		return append(true, str1, str2);
	}
	
	/**	
	 * 	结尾追加字符串
	 * 	
	 * 	@author Pan
	 * 	@param 	str1	字符串1
	 * 	@param 	strArr	字符串2
	 * 	@return	String
	 */
	public static String append(String str1, String... strArr) {
		return append(true, str1, strArr);
	}
	
	/**	
	 * 	追加字符串
	 * 	<br>自定义结尾或者开头追加字符串
	 * 	
	 * 	@author Pan
	 * 	@param 	str1	字符串1
	 * 	@param 	str2	字符串2
	 * 	@param 	isEnd	true在结尾添加，false在开头追加
	 * 	@return	String
	 */
	public static String append(boolean isEnd, String str1, String str2) {
		if (str1 == null) {
			if (str2 == null) {
				return null;
			}
			return str2;
		}

		if (isEnd) {
			return append(str1, str2, str1.length());
		}
		return append(str1, str2,  0);
	}
	
	/**	
	 * 	追加字符串
	 * 	<br>自定义结尾或者开头追加字符串
	 * 	<br>添加多个字符方式
	 * 
	 * 	@author Pan
	 * 	@param 	str1	字符串1
	 * 	@param 	array	字符串2
	 * 	@param 	isEnd	true在结尾添加，false在开头追加
	 * 	@return	String
	 */
	public static String append(boolean isEnd, String str1, String... array) {
		if (str1 == null) {
			if (ValidParam.isEmpty(array)) {
				return null;
			}
			return ArrayUtils.join(array, "");
		}
		
		StringBuilder createBuilder = createBuilder(str1);
		
		if (isEnd) {
			for (int i = 0; i < array.length; i++) {
				createBuilder.append(array[i]);
			}
			return createBuilder.toString();
		}
		
		for (int i = 0; i < array.length; i++) {
			createBuilder.insert(0, array[i]);
		}
		return createBuilder.toString();
	}

	/**
	 * 	字符插入
	 *
	 * 	@author Pan
	 * 	@param 	str			字符串
	 * 	@param 	offset		偏移量(插入下标)
	 * 	@param 	content		内容
	 * 	@return	String
	 */
	public static String append(String str, String content, int offset) {
		return createBuilder(str).insert(offset, content).toString();
	}

	/**
	 * 	判断字符串是否包含某个字符
	 * 	
	 * 	@author Pan
	 * 	@param 	str		字符串
	 * 	@param 	c		字符序列
	 * 	@return	boolean
	 */
	public static boolean contains(String str, char c) {
	    if (str == null) {
	        return false;
	    }
	    return str.indexOf(c) >= 0;
	}
	
	/**	
	 * 	判断字符串是否包含某个字符序列
	 * 	
	 * 	@author Pan
	 * 	@param 	str		字符串
	 * 	@param 	cs		字符序列
	 * 	@return	boolean
	 */
	public static boolean contains(String str, CharSequence cs) {
		if (str == null || cs == null) {
			return false;
		}
		return str.contains(cs);
	}
	
	/**	
	 * 	判断字符串是否包含某个字符序列
	 * 	
	 * 	@author Pan
	 * 	@param 	str		字符串
	 * 	@param 	cs		字符序列
	 * 	@return	boolean
	 */
	public static boolean contains(String str, CharSequence... cs) {
		if (str == null || cs == null || cs.length == 0) {
			return false;
		}
		
		for (int i = 0, len = cs.length; i < len; i++) {
			if (str.contains(cs[i])) {
				return true;
			}
		}
		return false;
	}
	
	/**	
	 * 	字符串是否包含集合中的某个值
	 * 	
	 * 	@author Pan
	 * 	@param 	str		字符
	 * 	@param 	list	集合
	 * 	@return	boolean
	 */
	public static boolean contains(String str, List<String> list) {
		if (ValidParam.isEmpty(list)) {
			return false;
		}
		
		for (int i = 0, len = list.size(); i < len; i++) {
			if (str.contains(list.get(i))) {
				return true;
			}
		}
		return false;
	}
	
	/**		
	 *	字符串是否包含Map中的某个Value
	 *	
	 * 	@author Pan
	 * 	@param  <K>     键类型
	 * 	@param 	str		字符串
	 * 	@param 	map		map
	 * 	@return	boolean
	 */
	public static <K> boolean contains(String str, Map<K, String> map) {
		if (map == null || map.size() == 0) {
			return false;
		}
		
		Iterator<String> iterator = IteratorUtils.values(map);
		while (iterator.hasNext()) {
			if (contains(str, iterator.next())) {
				return true;
			}
		}
		return false;
	}
	
	/**	
	 * 	字符串数组比较方法
	 * 	如果数组中存在值返回true
	 * 	
	 * 	@author Pan
	 * 	@param 	values			数组值
	 * 	@param 	equalsValue		需要对比的对象
	 * 	@return	boolean
	 */
	public static boolean contains(String[] values, String equalsValue) {
		if (ArrayUtils.isEmpty(values) || isEmpty(equalsValue)) {
			return false;
		}
		
		for (int i = 0, len = values.length; i < len; i++) {
			if (eq(values[i], equalsValue)) {
				return true;
			}
		}
		return false;
	}
	
	/**	
	 * 	字符串比较
	 * 	
	 * 	@author Pan
	 * 	@param 	s1	字符串1
	 * 	@param 	s2	字符串2
	 * 	@return	boolean
	 */
	public static boolean eq(String s1, String s2) {
		if (s1 == null) {
			return false;
		}
		return s1.equals(s2);
	}

	/**
	 * 	字符串与字符串缓冲比较
	 *
	 * 	@author Pan
	 * 	@param 	s1	字符串1
	 * 	@param 	s2	字符1
	 * 	@return	boolean
	 */
	public static boolean eq(String s1, StringBuilder s2) {
		if (s1 == null) {
			return false;
		}
		return s1.contentEquals(s2);
	}

	/**
	 * 	字符串与字符串缓冲比较
	 *
	 * 	@author Pan
	 * 	@param 	s1	字符串1
	 * 	@param 	s2	字符1
	 * 	@return	boolean
	 */
	public static boolean eq(String s1, StringBuffer s2) {
		if (s1 == null) {
			return false;
		}
		return s1.contentEquals(s2);
	}


	/**	
	 * 	字符串与字符比较
	 * 	
	 * 	@author Pan
	 * 	@param 	s1	字符串1
	 * 	@param 	c1	字符1
	 * 	@return	boolean
	 */
	public static boolean eq(String s1, Character c1) {
		return eq(s1, c1.toString());
	}
	
	/**	
	 * 	字符串比较
	 * 	<br>只要任意一个匹配返回true
	 * 
	 * 	@author Pan
	 * 	@param 	s1		字符串1
	 * 	@param 	strings	一个或多个字符串
	 * 	@return	boolean
	 */
	public static boolean eqOr(String s1, String... strings) {
		if (s1 == null || ValidParam.isEmpty(strings)) {
			return false;
		}
		
		for (int i = 0; i < strings.length; i++) {
			if (eq(s1, strings[i])) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 	字符串比较
	 * 	<br>只要任意一个匹配返回true
	 *
	 * 	@author Pan
	 * 	@param 	s1		字符串1
	 * 	@param 	list	字符串集合
	 * 	@return	boolean
	 */
	public static boolean eqOr(String s1, List<String> list) {
		if (s1 == null || ValidParam.isEmpty(list)) {
			return false;
		}

		for (int i = 0; i < list.size(); i++) {
			if (eq(s1, list.get(i))) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 	字符串与枚举比较
	 * 	<br>只要任意一个匹配返回true
	 *
	 * 	@author Pan
	 * 	@param 	s1		字符串
	 * 	@param 	es		一个或多个枚举
	 * 	@return	boolean
	 */
	public static boolean eqOr(String s1, Enum<?>... es) {
		if (s1 == null) {
			return false;
		}

		for (int i = 0; i < es.length; i++) {
			if (s1.equals(es[i].name())) {
				return true;
			}
		}
		return false;
	}

	/**	
	 * 	枚举值转换字符串对比
	 * 	
	 * 	@author Pan
	 * 	@param 	s1		字符串
	 * 	@param 	e1		枚举
	 * 	@return	boolean
	 */
	public static boolean compare(String s1, Enum<?> e1) {
		return eq(e1.name(), s1);
	}
	
	/**	
	 * 	字符串格式化
	 * 	<br>示例:
	 * 	<br>StringUtils.format("abc{}", "123");
	 *	<br>返回结果为:abc123
	 *	
	 * 	@author Pan
	 * 	@param  format	值
	 * 	@param  argument	参数
	 * 	@return	String
	 */
	public static String format(String format, Object... argument) {
		if (format == null || argument == null) {
			return Empty.strNull();
		}
		StringBuilder sbBuilder = new StringBuilder(format);
		
		int delimLen = FORMAT_DELIM_STR.length();
		int delimIndex = 0;
		for (int i = 0, len = argument.length; i < len; i++) {
			Object argumentObj = argument[i];
			
			delimIndex = sbBuilder.indexOf(FORMAT_DELIM_STR, delimIndex == 0 ? delimIndex : delimIndex + 1);
			if (delimIndex != -1) {
				sbBuilder.replace(delimIndex, delimIndex + delimLen, argumentObj == null ? Empty.strNull() : argumentObj.toString());
			}
		}
		return sbBuilder.toString();
	}

	/**
	 * 	找出非数字的字符串
	 *	<br>返回字符串
	 *
	 * 	@author Pan
	 * 	@param  str		字符串
	 * 	@return	String[]
	 */
	public static String findNonNumber(String str) {
		if (ValidParam.isEmpty(str)) {
			return null;
		}
		StringBuilder sb = new StringBuilder();

		for (int i = 0, len = str.length(); i < len; i++) {
			char c = str.charAt(i);

			if (!ValidParam.isNumber(c)) {
				sb.append(c);
			}
		}
		return sb.toString();
	}

	/**	
	 * 	找出非数字的字符串
	 * 	<br>返回数组
	 *
	 * 	@author Pan
	 * 	@param  str		字符串
	 * 	@return	String[]
	 */
	public static String[] findNonNumberToArray(String str) {
		if (ValidParam.isEmpty(str)) {
			return Empty.arrayString();
		}
		
		String[] arr = null;
		int arrLength = 0;
		int next = 0;

		for (int i = 0, len = str.length(); i < len; i++) {
			char c = str.charAt(i);

			if (!ValidParam.isNumber(c)) {
				if (arr == null) {
					arr = new String[10];
					arrLength = arr.length;
				}
				if (next >= arrLength) {
					arr = ArrayUtils.copy(arr, arrLength * 2);
					arrLength = arr.length;
				}
				arr[next++] = String.valueOf(c);
			}
		}

		if (arrLength != 0 && arrLength > next) {
			arr = ArrayUtils.copy(arr, next);
		}
		return arr;
	}

	/**
	 * 	找出非数字的字符串
	 * 	<br>返回集合
	 *
	 * 	@author Pan
	 * 	@param  str	字符串
	 * 	@return	List
	 */
	public static List<String> findNonNumberToList(String str) {
		if (ValidParam.isEmpty(str)) {
			return Empty.list();
		}
		
		int strLen = str.length();
		List<String> nonNumberList = CollUtils.newArrayList();
		for (int i = 0, len = strLen; i < len; i++) {
			char c = str.charAt(i);
			
			if (!ValidParam.isNumber(c)) {
				nonNumberList.add(String.valueOf(c));
			}
		}
		return nonNumberList;
	}

	/**	
	 * 	驼峰命名转换下划线-默认大写
	 * 
	 * 	@author Pan
	 * 	@param  str	字符串
	 * 	@return	String
	 */
	public static String humpToLine(String str) {
		return humpToLine(str, false);
	}
	
	/**	
	 * 	驼峰命名转换下划线
	 * 	
	 * 	@author Pan
	 * 	@param  str			字符串
	 * 	@param  toLowerCase	是否小写
	 * 	@return	String
	 */
	public static String humpToLine(String str, boolean toLowerCase) {
		int cLen = str.length();
		StringBuilder stringBuilder = new StringBuilder(cLen);
		
		for (int i = 0; i < cLen; i++) {
			char c = str.charAt(i);
			//	寻找大写字母
			if (ValidParam.isUpperCaseLetter(c)) {
				char uppercase = (c += 32);
				stringBuilder.append(LINE_TAG).append(uppercase);
				continue;
			}
			stringBuilder.append(c);
		}
		return toLowerCase ? stringBuilder.toString() : upperStr(stringBuilder.toString());
	}
	
	/**	
	 * 	字符串是否为空
	 * 	
	 * 	@author Pan
	 * 	@param 	param	参数
	 * 	@return	boolean
	 */
	public static boolean isEmpty(String param) {
		return param == null || param.length() == 0 || Empty.strNull().equalsIgnoreCase(param) || eq(Empty.str(), param.trim());
	}
	
	/**	
	 *  常量池
	 *  
	 * 	@author Pan
	 * 	@param  str		字符串
	 * 	@return	boolean
	 */
	public static boolean inPool(String str) {
		if (str == null) {
			return false;
		}
		return str.intern().equals(str);
	}

	/**
	 * 	首字母小写
	 * 	<br>首字母如果为数字 则返回原本值
	 * 
	 * 	@author Pan
	 * 	@param  str		字符串
	 * 	@return	String
	 */
	public static String lowerFirst(String str) {
		if (isEmpty(str) || Character.isDigit(str.charAt(0))) {
			return str;
		}

		StringBuilder stringBuilder = new StringBuilder(str);
		stringBuilder.replace(0, 1, String.valueOf(Character.toLowerCase(stringBuilder.charAt(0))));
		return stringBuilder.toString();
	}

	/**
	 * 	此字符串英文字母全部为小写
	 * 	
	 * 	@author Pan
	 * 	@param  str		字符串
	 * 	@return	String
	 */
	public static String lowerStr(String str) {
		if (isEmpty(str)) {
			return str;
		}
		
		char[] charArray = str.toCharArray();
		for (int i = 0; i < charArray.length; i++) {
			char c = charArray[i];
			if (ValidParam.isUpperCaseLetter(c)) {
				charArray[i] += 32;
			}
		}
		return String.valueOf(charArray);
	}

	/**
	 * 	下划线转换驼峰命名法
	 * 
	 * 	@author Pan
	 * 	@param  str		字符串
	 * 	@return	String
	 */
	public static String lineToHump(String str) {
		StringBuilder stringBuilder = new StringBuilder(lowerStr(str));
		//	因为替换之后indexOf需要加1才能找到字符
		int nextTag = 1;
		
		for (;;) {
			int indexOf = stringBuilder.indexOf(LINE_TAG);
			
			if (indexOf == -1) {
				break;
			} 
			//	替换_和下一个字母为空
			stringBuilder.replace(indexOf, indexOf + 2, "");
			//	找出下一个字符
			char c = str.charAt(indexOf + nextTag++);
			//	转换为首字母大写
			stringBuilder.insert(indexOf, upperStr(String.valueOf(c)));
		}
		return stringBuilder.toString();
	}
	
	/**	
	 * 	替换字符
	 * 	
	 * 	@author Pan
	 * 	@param 	str				字符串
	 * 	@param 	searchStr		搜索字符
	 * 	@param 	replaceStr		替换字符
	 * 	@return	String
	 */
	public static String replace(String str, String searchStr, String replaceStr) {
		if (isEmpty(str)) {
			return str;
		}
		
		StringBuilder sbBuilder = new StringBuilder(str);
		int indexOf = 0;
		
		for (;;) {
			//	避免替换时重复添加
			indexOf = sbBuilder.indexOf(searchStr, indexOf);
			if (indexOf < 0) {
				break;
			}
			
			sbBuilder.replace(indexOf, indexOf + searchStr.length(), replaceStr);
			++indexOf;
		}
		return sbBuilder.toString();
	}

	/**
	 * 	替换字符串方法
	 *	<br>按顺序标识符替换字符串
	 *	<br>需要替换的标识符全部一致 
	 *	<br>如字符串:{@code "xxxx{xxx},xxxx${xxx},xxxx${xxx}", 则需要${, }结尾,需要替换的a,b,c值，最终结果为"xxxxa,xxxxb,xxxxc"}
	 *
	 * 	@author Pan
	 * 	@param  str			字符串
	 * 	@param  startTag	开头的需要替换标识符
	 * 	@param  endTag		结束的需要替换标识符
	 * 	@param  replaceVal	替换的值
	 * 	@return	String
	 */
	public static String replaceByOrder(String str, String startTag, String endTag, String... replaceVal) {
		if (isEmpty(str)) {
			return str;
		}
		
		StringBuilder replaceBuilder = new StringBuilder(str);
		int valLen = replaceVal.length;
		
		for (int i = 0 ; i < valLen; i++) {
			int startIndexOf = replaceBuilder.indexOf(startTag);
			int endIndexOf = replaceBuilder.indexOf(endTag);
			
			if (startIndexOf > endIndexOf) {
				endIndexOf = replaceBuilder.indexOf(endTag, startIndexOf);
			}
			
			if (startIndexOf == -1 || endIndexOf == -1) {
				if (i == (valLen - 1)) {
					return replaceBuilder.toString();
				}
			} else {
				replaceBuilder.replace(startIndexOf, endIndexOf + 1, replaceVal[i]);
			}
		}
		return replaceBuilder.toString();
	}

	/**
	 * 	替换字符-如果为null返回null
	 * 	
	 * 	@author Pan
	 * 	@param 	str				字符串
	 * 	@param 	searchChar		搜索字符
	 * 	@param 	replaceChar		替换字符
	 * 	@return	String
	 */
	public static String replaceChars(final String str, final char searchChar, final char replaceChar) {
        return str == null ? null : str.replace(searchChar, replaceChar);
    }
	
	/**	
	 * 	移除包含匹配的字符
	 * 	
	 * 	@author Pan
	 * 	@param 	str			字符串
	 * 	@param  removeStr	移除字符
	 * 	@return	String
	 */
	public static String remove(String str, String removeStr) {
		return remove(str, removeStr, false);
	}
	
	/**
	 * 	移除包含匹配的字符或只移除第一个出现
	 * 	
	 * 	@author Pan
	 * 	@param 	str				字符串
	 * 	@param  removeStr		移除字符
	 * 	@param 	isRemoveFirst	是否只移除第一个匹配字符
	 * 	@return	String
	 */
	public static String remove(String str, String removeStr, boolean isRemoveFirst) {
		if (isEmpty(str) || isEmpty(removeStr)) {
			return str;
		}
		
		int indexOf = 0;
		StringBuilder sbBuilder = new StringBuilder(str);
		
		//	只移除一次	
		if (isRemoveFirst) {
			indexOf = sbBuilder.indexOf(removeStr);
			if (indexOf < 0) {
				return sbBuilder.toString();
			}
			return sbBuilder.replace(indexOf, indexOf + 1, Empty.str()).toString();
		}
		
		for (;;) {
			indexOf = sbBuilder.indexOf(removeStr);
			if (indexOf < 0) {
				break;
			} 
			sbBuilder.replace(indexOf, indexOf + 1, Empty.str());
		}
		return sbBuilder.toString();
	}
	
	/**	
	 * 	移除非数字
	 * 	<br>生成新字符串
	 * 
	 * 	@author Pan
	 * 	@param  str		字符串
	 * 	@return	String
	 */
	public static String removeNonNumber(String str) {
		StringBuilder strBuilder = new StringBuilder(str.length());
		
		char[] charArray = str.toCharArray();
		for (int i = 0, len = charArray.length; i < len; i++) {
			char c = charArray[i];
			if ((c >= '0' && c <= ':') || c == '.') {
				strBuilder.append(c);
			}
		}
		return strBuilder.toString();
	}
	
	/**	
	 * 	移除某个前缀
	 * 	
	 * 	@author Pan
	 * 	@param  str				字符串
	 * 	@param  removePrefix	前缀
	 * 	@return	String
	 */
	public static String removePrefix(String str, String removePrefix) {
		if (isEmpty(str)) {
			return str;
		}
		return str.startsWith(removePrefix) ? subStr(str, removePrefix.length(), str.length()) : str;
	}
	
	/**	
	 * 	移除某个后缀
	 * 	
	 * 	@author Pan
	 * 	@param  str				字符串
	 * 	@param  removeSuffix	后缀
	 * 	@return	String
	 */
	public static String removeSuffix(String str, String removeSuffix) {
		if (isEmpty(str)) {
			return str;
		}
		return str.endsWith(removeSuffix) ? subStr(str, 0, str.length() - removeSuffix.length()) : str;
	}

	/**	
	 * 	前缀匹配忽略大小写
	 * 
	 * 	@author Pan
	 * 	@param 	str		字符串
	 * 	@param 	prefix	前缀字符串
	 * 	@return	boolean	
	 */
	public static boolean startWithIgnoreCase(String str, String prefix) {
		if (str == null || prefix == null) {
			return false;
		}
		if (str.length() != prefix.length()) {
			return false;
		}
		
		int index = 0;
		int length = str.length();
		while (index < length) {
			char c1 = str.charAt(index);
            char c2 = prefix.charAt(index);
            
            if (c1 == c2) {
            	index++;
            	continue;
            }
            
            final char u1 = Character.toUpperCase(c1);
            final char u2 = Character.toUpperCase(c2);
            if (u1 != u2 && Character.toLowerCase(u1) != Character.toLowerCase(u2)) {
                return false;
            }
	        index++;
		}
		return true;
	}
	
	/**	
	 * 	字符串分割
	 * 	<br>默认保留空值
	 * 	<br>false示例:输入字符串为"1,2,3,"，分割符为","时，结果为["1", "2", "3", ""] 
	 * 
	 * 	@author Pan
	 * 	@param 	str			字符串
	 * 	@param 	delim		分隔符
	 * 	@return	String[]
	 */
	
	public static String[] split(String str, String delim) {
		return split(str, delim, false);
	}
	
	/**	
	 * 	字符串分割
	 * 	<br>自定义选择是否剔除空值
	 * 	<br>true示例:输入字符串为"1,2,3,"，分割符为","时，结果为["1", "2", "3"]，防止存在空值 
	 * 	<br>false示例:输入字符串为"1,2,3,"，分割符为","时，结果为["1", "2", "3", ""]
	 * 
	 * 	@author Pan
	 * 	@param  str			字符串
	 * 	@param  delim		分割字符
	 * 	@param  notEmpty	true 如果分割时substring下标为(0, 0) 或者(1, 1)情况下不添加值, false则添加值
	 * 	@return	String[]
	 */
	public static String[] split(String str, String delim, boolean notEmpty) {
		if (isEmpty(str) || delim == null) {
			return Empty.arrayString();
		}
		
		String[] split = new String[10];
		int nextSize = 0;
		int arrSize = split.length;
		int indexOf = 0;
		int lastIndex = 0;
		//	停止标识
		boolean stop = false;
		boolean firstAppend = true;
		
		while (!stop) {
			//	扩容
			if (nextSize >= arrSize) {
				split = ArrayUtils.copy(split, arrSize * 2);
				arrSize = split.length;
			}
			indexOf = str.indexOf(delim, indexOf);
			//	停止标识
			stop = indexOf < 0;
			
			String subStr = null;
			if (stop) {
				//	如果首次添加就已经未找到则返回原始字符串
				if (firstAppend) {
					return new String[] {str};
				}
				subStr = subStr(str, lastIndex + (delim.length() - 1));
			} else {
				subStr = subStr(str, lastIndex, indexOf);
			}
			
			//	是否添加空
			if (notEmpty && eq(Empty.str(), subStr)) {
				indexOf ++;
				lastIndex = indexOf;
				continue;
			}
			
			split[nextSize++] = subStr;
			indexOf ++;
			lastIndex = indexOf;
			firstAppend = false;
		}
		//	返回正确数组
		if (arrSize > nextSize) {
			split = ArrayUtils.copy(split, nextSize);
		}
		return split;
	}
	
	/**	
	 * 	字符串分割-可返回自定义分割数
	 * 	
	 * 	@author Pan
	 * 	@param 	str			字符串
	 * 	@param 	delim		分隔符
	 * 	@param 	maxArrLen	返回的分割数
	 * 	@return	String[]
	 */
	public static String[] split(String str, String delim, int maxArrLen) {
		List<String> split = splitToList(str, delim);
		if (ValidParam.isEmpty(split)) {
			return Empty.arrayString();
		}
		
		int listSize = split.size();
		//	重载方法标识位
		if (maxArrLen == -1) {
			maxArrLen = listSize;
		}
		
		//	最后填充长度
		int appendSize = listSize < maxArrLen ? listSize: maxArrLen;
		return split.subList(0, appendSize).toArray(new String[appendSize]);
	}
	
	/**	
	 * 	字符串分割
	 * 
	 * 	@author Pan
	 * 	@param  str		字符串
	 * 	@param  delim	分割字符
	 * 	@return	List
	 */
	public static List<String> splitToList(String str, String delim) {
		return splitToList(str, delim, true);
	}

	/**	
	 * 	字符串分割
	 * 	如果不存在该元素可剔除空值
	 * 	防止substring(0, 0) 为空的情况
	 * 	
	 * 	@author Pan
	 * 	@param  str			字符串
	 * 	@param  delim		分割字符
	 * 	@param  notEmpty	true 如果分割时substring下标为(0, 0) 或者(1, 1)情况下不添加值 false 则添加值
	 * 	@return	List
	 */
	public static List<String> splitToList(String str, String delim, boolean notEmpty) {
		List<String> list = CollUtils.newArrayList();
		int indexOf = 0;
		int lastIndex = 0;
		
		for (;;) {
			indexOf = str.indexOf(delim, indexOf);
			boolean stop = indexOf < 0;
			//					index = 0 校验分隔符超过2个字符长度正确识别		indexOf != 0 的情况下
			String sub = stop ? subStr(str, lastIndex + (delim.length() - 1)) : subStr(str, lastIndex, indexOf);
			
			if (notEmpty) {
				if (!Empty.str().equals(sub)) {
					list.add(sub);
				}
			} else {
				list.add(sub);
			}
			indexOf ++;
			lastIndex = indexOf;
			if (stop) {
				break;
			}
		}
		return list;
	}

	/**
	 * 	截取字符串-某位起始位至字符最后
	 * 	
	 * 	@author Pan
	 * 	@param 	str		字符
	 * 	@param 	start	起始下标
	 * 	@return	String
	 */
	public static String subStr(String str, int start) {
		return str == null ? null : subStr(str, start, str.length());
	}

	/**	
	 * 	截取字符串-某起始位至某结束位
	 * 	
	 * 	@author Pan
	 * 	@param 	str		字符串
	 * 	@param 	start	起始下标		
	 * 	@param 	end		结束下标
	 * 	@return	String
	 */
	public static String subStr(String str, int start, int end) {
		if (isEmpty(str)) {
			return null;
		}
		
		if ((start < 0 || end < 0) || 
				start == end	   ||
				start > end 	   ||
				end > str.length()) {
			return Empty.str();
		}
		return str.substring(start, end);
	}

	/**	
	 * 	相似度
	 * 	
	 * 	@author Pan
	 * 	@param 	str		字符串
	 * 	@param 	target	目标字符串
	 * 	@return	float
	 */
	public static float similarityRatio(String str, String target) {
		int n = str.length();
		int m = target.length();
		int i; // 遍历str的
		int j; // 遍历target的
		char ch1; // str的
		char ch2; // target的
		int temp; // 记录相同字符,在某个矩阵位置值的增量,不是0就是1
		if (n == 0 || m == 0) {
			return 0;
		}
		// 矩阵
		int[][] d = new int[n + 1][m + 1];
		for (i = 0; i <= n; i++) { // 初始化第一列
			d[i][0] = i;
		}

		for (j = 0; j <= m; j++) { // 初始化第一行
			d[0][j] = j;
		}

		for (i = 1; i <= n; i++) { // 遍历str
			ch1 = str.charAt(i - 1);
			// 去匹配target
			for (j = 1; j <= m; j++) {
				ch2 = target.charAt(j - 1);
				if (ch1 == ch2 || ch1 == ch2 + 32 || ch1 + 32 == ch2) {
					temp = 0;
				} else {
					temp = 1;
				}
				// 左边+1,上边+1, 左上角+temp取最小
				d[i][j] = Math.min(Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1), d[i - 1][j - 1] + temp);
			}
		}
		return (1 - (float) d[n][m] / Math.max(str.length(), target.length())) * 100F;
	}
	
	/**
	 * 	首字母大写
	 * 	
	 * 	@author Pan
	 * 	@param  str		字符串
	 * 	@return	String
	 */
	public static String upperFirst(String str) {
		if (isEmpty(str) || Character.isDigit(str.charAt(0))) {
			return str;
		}
		
		char[] charArray = str.toCharArray(); 
		charArray[0] -= 32;
		
		return String.valueOf(charArray);
	}
	
	/**	
	 * 	此字符串英文字母全部为大写
	 * 	
	 * 	@author Pan
	 * 	@param  str		字符串
	 * 	@return	String
	 */
	public static String upperStr(String str) {
		if (isEmpty(str)) {
			return str;
		}
		
		char[] charArray = str.toCharArray();
		for (int i = 0; i < charArray.length ; i++) {
			if (ValidParam.isLowerCaseLetter(charArray[i])) {
				charArray[i] -= 32;
			}
		}
		return String.valueOf(charArray);
	}
	
	/**	
	 * 	创建StringBuilder
	 * 	
	 * 	@author Pan
	 * 	@return	StringBuilder
	 */
	public static StringBuilder createBuilder() {
		return new StringBuilder();
	}
	
	/**	
	 * 	创建StringBuilder
	 * 
	 * 	@author Pan
	 * 	@param 	str		字符串
	 * 	@return	StringBuilder
	 */
	public static StringBuilder createBuilder(String str) {
		return new StringBuilder(str);
	}
	
	/**	
	 * 	创建StringBuilder
	 * 
	 * 	@author Pan
	 * 	@param 	obj		对象
	 * 	@return	StringBuilder
	 */
	public static StringBuilder createBuilder(Object obj) {
		return new StringBuilder().append(obj);
	}

	/**
	 *  字符串前后去除空格
	 *  <br>默认采用jdk实现，后新增了对中文空格的处理
	 *
	 * 	@param  str 字符串
	 * 	@return String
	 */
	public static String trim(String str) {
		if (str == null) {
			return null;
		}

		int len = str.length();
		int st = 0;
		char[] val = str.toCharArray();

		while ((st < len) && (val[st] <= ' ' && val[st] <= '\u3000')) {
			st++;
		}
		while ((st < len) && (val[len - 1] <= ' ' && val[st] <= '\u3000')) {
			len--;
		}
		return ((st > 0) || (len < str.length())) ? subStr(str, st, len) : str;
	}

	/**
	 * 	将清除字符串中换行符、回车符、缩进符
	 *
	 * 	@author Pan
	 * 	@param 	str		字符串
	 * 	@return	String
	 */
	public static String cleanLine(String str) {
		StringBuilder strBuilder = new StringBuilder();

		for (int i = 0; i < str.length(); i++) {
			char c = str.charAt(i);
			if (c != '\t' && c != '\n' && c != '\r') {
				strBuilder.append(c);
			}
		}
		return strBuilder.toString();
	}

	/**
	 * 	将清除字符串中的特殊字符
	 * 	<br>包含：空格、全角空格、换行符、缩进符、回车符
	 *  <br>返回清理后的String
	 *
	 * 	@author Pan
	 * 	@param  str		字符串
	 * 	@return String
	 */
	public static String cleanSpecial(String str) {
		return cleanSpecial(str, false);
	}

	/**
	 * 	将清除字符串中的特殊字符
	 * 	<br>包含：空格、全角空格、换行符、缩进符、回车符
	 * <br>返回清理后的String
	 *
	 * 	@author Pan
	 * 	@param  chars	字符数组
	 * 	@return	String
	 */
	public static String cleanSpecial(char[] chars) {
		return cleanSpecial(new String(chars), false);
	}

	/**
	 * 	将清除字符串中的特殊字符
	 *  <br>模式有空格和全角空格或清除全角符号
	 * 	<br>返回清理后的String
	 * 	<br>true时清除空格、全角空格、全角符号
	 * 	<br>false时清除空格、全角空格、换行符、缩进符、回车符
	 *
	 * 	@author Pan
	 * 	@param  str			字符串
	 * 	@param  cleanMode	true时清除空格、全角空格、全角符号, false时清除字符串空格、全角空格、换行符、缩进符、回车符
	 * 	@return String
	 */
	public static String cleanSpecial(String str, boolean cleanMode) {
		if (isEmpty(str)) {
			return str;
		}
		StringBuilder strBuilder = new StringBuilder();

		for (int i = 0, len = str.length(); i < len; i++) {
			char c = str.charAt(i);

			if (cleanMode) {
				if (!ValidParam.isContainsSpace(c) && !ValidParam.isFullWidthCharacter(c)) {
					strBuilder.append(c);
				}
			} else {
				if (!ValidParam.isContainsSpace(c) && c != '\t' && c != '\n' && c != '\r') {
					strBuilder.append(c);
				}
			}
		}
		return strBuilder.toString();
	}

}
